#include "main.h"
#include "TypeDlg.h"

/*
 * AddChildDialog
 * - Add a dialog ONTO an existing dialog!
 */
HWND AddChildDialog(HWND hWnd, UINT dlgID, DLGPROC dlgProc, int nX, int nY)
{
	/*
	 * Create new dialog and position it (based on function parameters)
	 */
	HWND hNewChild = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(dlgID), hWnd, dlgProc);
	SetWindowPos(hNewChild, NULL, nX, nY, 0, 0, SWP_NOSIZE | SWP_NOZORDER);

	/*
	 * Resize main window to accomadate for the height increase
	 */
	RECT rcSize, rcWinSize;

	GetWindowRect(hNewChild, &rcSize);
	GetWindowRect(hWnd, &rcWinSize);

	SetWindowPos(hWnd, NULL, 0, 0, rcWinSize.right - rcWinSize.left, (rcWinSize.bottom - rcWinSize.top) + (rcSize.bottom - rcSize.top), SWP_NOZORDER | SWP_NOMOVE);

	/*
	 * Show child window
	 */
	ShowWindow(hNewChild, SW_SHOW);

	return hNewChild;
}

/*
 * RemoveChlidDialog
 * - Remove a dialog that was previously added onto a dialog
 */
void RemoveChildDialog(HWND hParent, HWND hWnd)
{
	/*
	 * Resize parent to adapt to less height because of dialog removal
	 */
	RECT rcSize, rcWinSize;

	GetWindowRect(hWnd, &rcSize);
	GetWindowRect(hParent, &rcWinSize);

	SetWindowPos(hParent, NULL, 0, 0, rcWinSize.right - rcWinSize.left, (rcWinSize.bottom - rcWinSize.top) - (rcSize.bottom - rcSize.top), SWP_NOZORDER | SWP_NOMOVE);

	/*
	 * Send close message to child dialog
	 */
	SendMessage(hWnd, WM_CLOSE, 0, 0);
}

/*
 * dlgTypeServerProc
 * - Message handler for "server" type (setting params)
 */
BOOL CALLBACK dlgTypeServerProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_INITDIALOG:
		/*
		 * Default edit boxes
		 */
		SetDlgItemInt(hWnd, IDC_EDIT_PORT, 7654, FALSE);
		SetDlgItemInt(hWnd, IDC_EDIT_MAXUSERS, 5, FALSE);
		SetDlgItemText(hWnd, IDC_EDIT_SERVERID, "MyUsername");
		break;

	/*
	 * Custom message to validate data
	 */
	case CWM_VALIDATE: // Custom message, validate text.
		{
			/*
			 * Verify that a valid port, max users, and user ID is filled in
			 */
			UINT nMaxUsers = GetDlgItemInt(hWnd, IDC_EDIT_MAXUSERS, NULL, FALSE);
			UINT nPort = GetDlgItemInt(hWnd, IDC_EDIT_PORT, NULL, FALSE);
			int nLength = GetWindowTextLength(GetDlgItem(hWnd, IDC_EDIT_SERVERID));
			if (nMaxUsers <= 1)
				MessageBox(hWnd, "Max users must be greater than one.", "Error", MB_ICONERROR | MB_OK);
			else if (nPort <= 0)
				MessageBox(hWnd, "Please enter a valid port.", "Error", MB_ICONERROR | MB_OK);
			else if (nLength <= 0)
				MessageBox(hWnd, "Please enter a valid user ID.", "Error", MB_ICONERROR | MB_OK);
			else
			{
				/*
				 * Fill in dataReturn. See main.cpp and main.h for info on dlgReturn type
				 */
				char *cBuf = NULL;
				cBuf = (char *)malloc(nLength + 1);
				GetDlgItemText(hWnd, IDC_EDIT_SERVERID, cBuf, nLength + 1);

				dlgReturn *dataReturn = (dlgReturn *)malloc(sizeof(dlgReturn));
				dataReturn->dlgID = IDD_SERVER;
				dataReturn->lpDlgProc = dlgServerProc;
				dataReturn->params = (UINT *)calloc(3, sizeof(UINT));

				dataReturn->params[0] = nMaxUsers;
				dataReturn->params[1] = nPort;
				dataReturn->params[2] = (UINT)cBuf;

				/*
				 * Confusing? Pointer to a pointer. Basically: a pointer to a memory address
				 * We know the memory address of the dataReturn we made, so we're filling in
				 * the pointer to it, with the memory address of it.
				 */
				dlgReturn **dataAdd = (dlgReturn **)wParam;
				*dataAdd = dataReturn;
			}
		}
		break;

	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;

	default:
		return FALSE;
	}
	return TRUE;
}

/*
 * dlgTypeClientProc
 * - Message handler for "client" type selection (to set parameters)
 */
BOOL CALLBACK dlgTypeClientProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_INITDIALOG:
		/*
		 * Default edit boxes
		 */
		SetDlgItemText(hWnd, IDC_EDIT_USERID, "MyUsername");
		break;

	/*
	 * Custom message to validate data
	 */
	case CWM_VALIDATE: // Custom message, validate text.
		{
			/*
			 * Make sure user ID is filled in
			 */
			int nLength = GetWindowTextLength(GetDlgItem(hWnd, IDC_EDIT_USERID));
			char *cBuf = NULL;
			if (nLength <= 0)
				MessageBox(hWnd, "You must enter a user ID.", "Error", MB_ICONERROR | MB_OK);
			else
			{
				/*
				 * Fill in dataReturn. See main.cpp and main.h for info on dlgReturn type
				 */
				cBuf = (char *)malloc(nLength + 1);
				GetDlgItemText(hWnd, IDC_EDIT_USERID, cBuf, nLength + 1);

				dlgReturn *dataReturn = (dlgReturn *)malloc(sizeof(dlgReturn));
				dataReturn->dlgID = IDD_CLIENT;
				dataReturn->lpDlgProc = dlgClientProc;
				dataReturn->params = (UINT *)calloc(1, sizeof(UINT));

				dataReturn->params[0] = (UINT)cBuf;

				/*
				 * Confusing? Pointer to a pointer. Basically: a pointer to a memory address
				 * We know the memory address of the dataReturn we made, so we're filling in
				 * the pointer to it, with the memory address of it.
				 */
				dlgReturn **dataAdd = (dlgReturn **)wParam;
				*dataAdd = dataReturn;
			}
		}
		break;

	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;

	default:
		return FALSE;
	}
	return TRUE;
}

/*
 * dlgTypeProc
 * - Message handler for main type dialog
 */
BOOL CALLBACK dlgTypeProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static HWND s_hMini = NULL;
	static byte s_bShow = 0;

	switch (msg)
	{
	case WM_INITDIALOG:
		/* 
		 * Center window onto the screen
		 */
		CenterOnScreen(hWnd);
		break;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		/*
		 * "server" type
		 * Display "server" child dialog to set parameters
		 */
		case IDC_SERVER:
			if (s_bShow != 1)
			{
				/*
				 * If child dialog set, remove it
				 */
				if (s_hMini != NULL)
					RemoveChildDialog(hWnd, s_hMini);

				/*
				 * Add new child dialog
				 */
				s_hMini = AddChildDialog(hWnd, IDD_TYPE_SERVER, dlgTypeServerProc, 5, 60);

				/*
				 * Set current showing to 1 ("server")
				 */
				s_bShow = 1;
			}
			break;

		/*
		 * "client" type
		 * Display "client" child dialog to set parameters
		 */
		case IDC_CLIENT:
			if (s_bShow != 2)
			{
				/*
				 * If child dialog set, remove it
				 */
				if (s_hMini != NULL)
					RemoveChildDialog(hWnd, s_hMini);

				/*
				 * Add new child dialog
				 */
				s_hMini = AddChildDialog(hWnd, IDD_TYPE_CLIENT, dlgTypeClientProc, 5, 60);

				/*
				 * Set current showing to 2 ("client")
				 */
				s_bShow = 2;			
			}
			break;

		/*
		 * "Okay" clicked
		 */
		case IDC_OK:
			/*
			 * If no type selected...
			 */
			if (s_bShow == 0)
				MessageBox(hWnd, "You must select whether you wish to be the client or the server.", "Error", MB_ICONERROR | MB_OK);
			// Otherwise...
			else
			{
				/*
				 * Send validate message to child dialog. It'll fill dataReturn
				 */
				dlgReturn *dataReturn = NULL;
				bool bWorked = false;
				SendMessage(s_hMini, CWM_VALIDATE, (WPARAM)&dataReturn, 0);

				if (dataReturn != NULL)
				{
					// Success. Remove child dialog and End this dialog
					RemoveChildDialog(hWnd, s_hMini);
					EndDialog(hWnd, (int)dataReturn);
				}
			}
			break;
		}
		break;

	case WM_CLOSE:
		/*
		 * End dialog with "0" return meaning cancel (no type selected)
		 */
		EndDialog(hWnd, 0);
		break;

	default:
		return FALSE;
	}
	return TRUE;
}